package com.wfh.core.builder;

import cn.hutool.core.util.RuntimeUtil;
import com.wfh.service.SseService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.concurrent.TimeUnit;

/**
 * @Title: VueProjectBuilder
 * @Author wangfenghuan
 * @Package com.wfh.aigenerator.core.builder
 * @Date 2025/8/7 14:48
 * @description:
 */
@Slf4j
@Component
public class VueProjectBuilder {


    @Resource
    private SseService sseService;

    /**
     * 异步构建项目（不阻塞主流程）
     *
     * @param projectPath 项目路径
     */
    public boolean buildProjectAsync(String projectPath, Long taskId) {
        // 在单独的线程中执行构建，避免阻塞主流程,使用的虚拟线程
        Thread.ofVirtual().name("vue-builder-" + System.currentTimeMillis()).start(() -> {
            try {
                boolean b = buildProject(projectPath, taskId);
            } catch (Exception e) {
                log.error("异步构建 Vue 项目时发生异常: {}", e.getMessage(), e);
            }
        });
        return true;
    }

    public boolean buildProject(String projectPath, Long taskId) {
        // 先开始发送事件
        sseService.sendMessage(taskId, "start", "开始构建 Vue 项目，根目录");
        File projectDir = new File(projectPath);

        log.info("开始构建 Vue 项目，根目录: {}", projectDir.getAbsolutePath());

        if (!projectDir.exists()) {
            log.error("项目路径不存在: {}", projectPath);
            return false;
        }

        if (!projectDir.isDirectory()) {
            log.error("项目路径不是一个目录: {}", projectPath);
            return false;
        }

        // 第一步：检查当前目录是否有 package.json
        File packageJson = new File(projectDir, "package.json");
        File actualProjectDir = null;

        if (packageJson.exists()) {
            log.info("在根目录找到 package.json: {}", packageJson.getAbsolutePath());
            actualProjectDir = projectDir;
        } else {
            log.info("根目录未找到 package.json，正在查找子目录...");
            // 查找第一层子目录中是否有 package.json
            File[] subDirs = projectDir.listFiles(File::isDirectory);
            if (subDirs != null) {
                for (File subDir : subDirs) {
                    File subPackageJson = new File(subDir, "package.json");
                    if (subPackageJson.exists()) {
                        actualProjectDir = subDir;
                        log.info("在子目录中找到 package.json: {}", subPackageJson.getAbsolutePath());
                        break;
                    }
                }
            }

            if (actualProjectDir == null) {
                log.error("在目录 {} 及其第一层子目录中均未找到 package.json 文件", projectPath);
                return false;
            }
        }

        // 现在 actualProjectDir 是真正的项目根目录
        log.info("使用项目目录进行构建: {}", actualProjectDir.getAbsolutePath());

        // 执行 npm install 和 npm run build
        sseService.sendMessage(taskId, "running", "正在执行 npm install");
        if (!executeNpmInstall(actualProjectDir)) {
            log.error("npm install 执行失败: {}", actualProjectDir.getAbsolutePath());
            sseService.sendMessage(taskId, "error", "npm install 失败");
            return false;
        }
        sseService.sendMessage(taskId, "running", "正在执行 npm run build");
        if (!executeNpmBuild(actualProjectDir)) {
            log.error("npm run build 执行失败: {}", actualProjectDir.getAbsolutePath());
            sseService.sendMessage(taskId, "error", "npm run build 失败");
            return false;
        }

        // 验证 dist 目录是否生成
        File distDir = new File(actualProjectDir, "dist");

        if (!distDir.exists()) {
            log.error("构建完成，但 dist 目录未生成: {}", distDir.getAbsolutePath());
            return false;
        }
        sseService.sendMessage(taskId, "finish", "构建完成请刷新网站预览页面");
        log.info("Vue 项目构建完成: {}", actualProjectDir.getAbsolutePath());
        // 当前应用构建完成主动关闭连接
        sseService.complete(taskId);
        return true;
    }

    /**
     * 执行命令
     *
     * @param workingDir     工作目录
     * @param command        命令字符串
     * @param timeoutSeconds 超时时间（秒）
     * @return 是否执行成功
     */
    private boolean executeCommand(File workingDir, String command, int timeoutSeconds) {
        try {
            log.info("在目录 {} 中执行命令: {}", workingDir.getAbsolutePath(), command);
            Process process = RuntimeUtil.exec(
                    null,
                    workingDir,
                    // 命令分割为数组
                    command.split("\\s+")
            );
            // 等待进程完成，设置超时
            boolean finished = process.waitFor(timeoutSeconds, TimeUnit.SECONDS);
            if (!finished) {
                log.error("命令执行超时（{}秒），强制终止进程", timeoutSeconds);
                process.destroyForcibly();
                return false;
            }
            int exitCode = process.exitValue();
            if (exitCode == 0) {
                log.info("命令执行成功: {}", command);
                return true;
            } else {
                log.error("命令执行失败，退出码: {}", exitCode);
                return false;
            }
        } catch (Exception e) {
            log.error("执行命令失败: {}, 错误信息: {}", command, e.getMessage());
            return false;
        }
    }
    /**
     * 执行 npm install 命令
     */
    private boolean executeNpmInstall(File projectDir) {
        log.info("执行 npm install...");
        String command = String.format("%s install", buildCommand("npm"));
        // 5分钟超时
        return executeCommand(projectDir, command, 600);
    }

    /**
     * 执行 npm run build 命令
     */
    private boolean executeNpmBuild(File projectDir) {
        log.info("执行 npm run build...");
        String command = String.format("%s run build", buildCommand("npm"));
        // 3分钟超时
        return executeCommand(projectDir, command, 180);
    }


    /**
     * 判断操作系统的类型
     * @return
     */
    private boolean isWindows() {
        return System.getProperty("os.name").toLowerCase().contains("windows");
    }

    /**
     * 构建命令
     * @param baseCommand
     * @return
     */
    private String buildCommand(String baseCommand) {
        if (isWindows()) {
            return baseCommand + ".cmd";
        }
        return baseCommand;
    }



}

